/******************************************************************************
 * This module contains some methods for classes from FOBJECTS.H              *
 ******************************************************************************/

#include <math.h>
#ifdef __GNUC__
#include <string.h>
#else
#include <mem.h>
#endif
#include "fobjects.h"

/******************************************************************************
 * Copy one Filter object to the other.                                       *
 ******************************************************************************/
const Filter &Filter::operator=(const Filter &Src)
{
  int i;
  assert(Src.Bands);
  if(&Src != this)
  {
    if(Bands)
      DELETE_ARRAY(Bands, NoBands);
    Bands = new BandInfo[NoBands = Src.NoBands];
    for(i = 0; i < NoBands; i++)
      Bands[i] = Src.Bands[i];
  }
  return (*this);
}

/******************************************************************************
 * Copy one Vector object to the other.                                       *
 ******************************************************************************/

const Vector &Vector::operator=(const Vector &Src)
{
  assert(Src.tbl);
  if(&Src != this)
  {
    if(tbl)
      DELETE_ARRAY(tbl, Hi - Lo + 1);
    tbl = new Float[(Hi = Src.Hi) - (Lo = Src.Lo) + 1];
    memmove(tbl, Src.tbl, (Hi - Lo + 1) * sizeof(Float));
  }
  return (*this);
}

/******************************************************************************
 * Set new bounds for Vector. Previous contents is lost.                      *
 ******************************************************************************/
void Vector::SetDims(int _Lo, int _Hi)
{
  assert(_Hi >= _Lo);
  if(tbl)
    DELETE_ARRAY(tbl, Hi - Lo + 1);
  tbl = new Float[(Hi = _Hi) - (Lo = _Lo) + 1];
}

/******************************************************************************
 * Find, if value x is located anywhere inside Vector V.                      *
 ******************************************************************************/
int In(const Vector &V, Float x)
{
  int i;
  for(i = 0; i <= V.Hi - V.Lo; i++)
    if(Eq(x, V.tbl[i]))
      return (1);
  return (0);
}

/******************************************************************************
 * Copy one Array object to the other.                                        *
 ******************************************************************************/
const Array &Array::operator=(const Array &Src)
{
  assert(Src.tbl);
  if(&Src != this)
  {
    if(tbl)
      DELETE_ARRAY(tbl, Hi - Lo + 1);
    tbl = new Vector[(Hi = Src.Hi) - (Lo = Src.Lo) + 1];
    for(int i = 0; i <= Hi - Lo; i++)
      tbl[i] = Src.tbl[i];
  }
  return (*this);
}

/******************************************************************************
 * Set new bounds for Array. Previous contents is lost.                       *
 ******************************************************************************/
void Array::SetDims(int _Lo, int _Hi)
{
  assert(_Hi >= _Lo);
  if(tbl)
    DELETE_ARRAY(tbl, Hi - Lo + 1);
  tbl = new Vector[(Hi = _Hi) - (Lo = _Lo) + 1];
}

/******************************************************************************
 * Find, if value x is located anywhere inside Array A.                       *
 ******************************************************************************/
int In(const Array &A, Float x)
{
  int i;
  for(i = 0; i <= A.Hi - A.Lo; i++)
    if(In(A.tbl[i], x))
      return (1);
  return (0);
}

/******************************************************************************
 * Removes contents of the list.                                              *
 ******************************************************************************/
void List::RemoveList(void)
{
  while(First)
  {
    Curr = First;
    First = First->Next;
    delete Curr;
  }
  First = Last = Curr = 0;
}

/******************************************************************************
 * Add value Val after Last node in the list. Updates Last as neccessary.     *
 ******************************************************************************/
void List::Add(Float Val)
{
  Node *p;
  p = new Node(Val);
  if(!First)
    Curr = First = Last = p;
  else
  {
    p->Prev = Last;
    Last->Next = p;
    Curr = Last = p;
  }
}

/******************************************************************************
 * Add value Val after Curr node in the list. Updates Curr and Last as        *
 * neccessary.                                                                *
 ******************************************************************************/
void List::InsertAfter(Float Val)
{
  Node *p;
  p = new Node(Val);
  if(!First)
    First = Last = Curr = p;
  else
    if(!Curr)
    {
      p->Prev = Last;
      Curr = Last = Last->Next = p;
    }
    else
    {
      p->Prev = Curr;
      p->Next = Curr->Next;
      if(Curr->Next)
        Curr->Next->Prev = p;
      else
        Last = p;
      Curr = Curr->Next = p;
    }
}

/******************************************************************************
 * Add value Val before Curr node in the list. Updates Curr and First as      *
 * neccessary.                                                                *
 ******************************************************************************/
void List::InsertBefore(Float Val)
{
  Node *p;
  p = new Node(Val);
  if(!First)
    First = Last = Curr = p;
  else
    if(!Curr)
    {
      p->Next = First;
      Curr = First = First->Prev = p;
    }
    else
    {
      p->Next = Curr;
      p->Prev = Curr->Prev;
      if(Curr->Prev)
        Curr->Prev->Next = p;
      else
        First = p;
      Curr = Curr->Prev = p;
    }
}

/******************************************************************************
 * Find, if value x is located anywhere inside List L.                        *
 ******************************************************************************/
int In(const List &L, Float Val)
{
  Node *p;
  for(p = L.First; p; p = p->Next)
    if(Eq(p->Val, Val))
      return (1);
  return (0);
}

/******************************************************************************
 * Applies cosine function to each element of Src, and returns Array of these *
 * values.                                                                    *
 ******************************************************************************/
Array cos(const Array &Src)
{
  Array p(1, Hi(Src));
  int i, j;
  for(i = 1; i <= Hi(p); i++)
  {
    p[i].SetDims(1, Hi(Src[i]));
    for(j = 1; j <= Hi(p[i]); j++)
      p[i][j] = cos(Src[i][j]);
  }
  return (p);
}
